package com.ququ.syb.business.withdraw.service;

import com.ququ.common.result.Result;
import com.ququ.syb.business.withdraw.fegin.*;
import com.ququ.syb.business.withdraw.rabbitmq.RabbitMQSender;
import com.ququ.syb.common.constant.FlowTypeConstant;
import com.ququ.syb.common.constant.PayChannelClearTypeConstant;
import com.ququ.syb.common.constant.RabbitMqQueueNameConstant;
import com.ququ.syb.common.constant.WithdrawStatusConstant;
import com.ququ.syb.common.pojo.AccountChannelBalance;
import com.ququ.syb.common.pojo.PayChannel;
import com.ququ.syb.common.pojo.PayOrder;
import com.ququ.syb.common.pojo.WithdrawOrder;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
public class WithdrawBusinessService {
    @Autowired
    private WithdrawOrderFegin withdrawOrderFegin;
    @Autowired
    private BalanceFegin balanceFegin;
    @Autowired
    private WithdrawOrderService withdrawOrderService;
    @Autowired
    private PayChannelFegin payChannelFegin;
    @Autowired
    private RabbitMQSender rabbitMQSender;
    @Autowired
    private FlowFegin flowFegin;
    @Autowired
    private PayOrderFegin payOrderFegin;

    private Logger logger = LoggerFactory.getLogger(WithdrawBusinessService.class);


    /**
     * 创建提现订单
     */
    public Result<WithdrawOrder> createWithdrawOrder(String accountid, String tradenum, String outordernum, Long amount, String paychannelid, String appcode, Integer type, Integer withdrawtype, String callbackurl, String paytradenum){
        WithdrawOrder withdrawOrder = null;
        if (StringUtils.isNotBlank(paytradenum)){
            PayOrder payOrder = payOrderFegin.getPayOrder(paytradenum).getData();
            PayChannel payChannel = payChannelFegin.getPayChannel(payOrder.getPaychannelid()).getData();
            switch (payChannel.getIsAutoClear()) {
                case PayChannelClearTypeConstant.REAL_DIRECT_CLEAR:
                    withdrawOrder = withdrawOrderService.createDirectVirtualWithdrawOrder(paytradenum).getData();
                    break;
                case PayChannelClearTypeConstant.FAKE_DIRECT_CLEAR:
                    withdrawOrder = withdrawOrderService.createDirectClearWithdrawOrder(paytradenum).getData();
                    break;
                default:
                    return new Result<>(-1,"不是直清或伪直清通道，支付订单号必须为空");
            }
        }else
            withdrawOrder = withdrawOrderService.createWithdrawOrder(accountid, tradenum, outordernum, amount, paychannelid, appcode, type, withdrawtype, callbackurl, null).getData();
        //资金预占
        withdrawDeduct(withdrawOrder);
        //通道资金预占
        withdrawChannelDeduct(withdrawOrder);
        //应用资金预占
        withdrawAppDeduct(withdrawOrder);
        //丢入提现处理队列
        rabbitMQSender.send(RabbitMqQueueNameConstant.AUDIT_WITHDRAWAL_SUCCESS,withdrawOrder.getTradenum());
        return new Result<>(withdrawOrder);
    }

    /**
     * 提现资金预占
     */
    public AccountChannelBalance withdrawDeduct(WithdrawOrder withdrawOrder){
        AccountChannelBalance accountChannelBalance = balanceFegin.addBalance(withdrawOrder.getAccountid(),
                withdrawOrder.getPaychannelid(),
                0-withdrawOrder.getAmount()+withdrawOrder.getCustomercommission(),
                2,
                withdrawOrder.getTradenum(),
                FlowTypeConstant.WITHDRAW,
                withdrawOrder.getAppcode(),
                "账户提现金额预占").getData();
        logger.debug("账户提现金额预占后:{}",accountChannelBalance);
        if (withdrawOrder.getCustomercommission()>0) {
            accountChannelBalance = balanceFegin.addBalance(withdrawOrder.getAccountid(),
                    withdrawOrder.getPaychannelid(),
                    0 - withdrawOrder.getCustomercommission(),
                    2,
                    withdrawOrder.getTradenum(),
                    FlowTypeConstant.WITHDRAW_COMMISSION,
                    withdrawOrder.getAppcode(),
                    "账户提现手续费预占").getData();
            logger.debug("账户提现手续费预占后:{}", accountChannelBalance);
        }
        return accountChannelBalance;
    }


    /**
     * 提现通道预占
     * @param withdrawOrder
     * @return
     */
    public AccountChannelBalance withdrawChannelDeduct(WithdrawOrder withdrawOrder){
        PayChannel payChannel = payChannelFegin.getPayChannel(withdrawOrder.getPaychannelid()).getData();
        AccountChannelBalance accountChannelBalance = balanceFegin.addBalance(payChannel.getAccountid().toString(),
                withdrawOrder.getPaychannelid(),
                0-withdrawOrder.getAmount()+withdrawOrder.getCustomercommission(),
                2,
                withdrawOrder.getTradenum(),
                FlowTypeConstant.WITHDRAW,
                withdrawOrder.getAppcode(),
                "通道账户提现金额预占").getData();
        logger.debug("通道账户提现金额预占后:{}",accountChannelBalance);
        if (withdrawOrder.getCommission()>0) {
            accountChannelBalance = balanceFegin.addBalance(payChannel.getAccountid().toString(),
                    withdrawOrder.getPaychannelid(),
                    0 - withdrawOrder.getCommission(),
                    2,
                    withdrawOrder.getTradenum(),
                    FlowTypeConstant.WITHDRAW_COMMISSION,
                    withdrawOrder.getAppcode(),
                    "通道账户提现手续费预占").getData();
            logger.debug("通道账户提现手续费预占后:{}", accountChannelBalance);
        }
        return accountChannelBalance;
    }


    /**
     * 提现应用预占
     * @param withdrawOrder
     * @return
     */
    public AccountChannelBalance withdrawAppDeduct(WithdrawOrder withdrawOrder){
        AccountChannelBalance accountChannelBalance = balanceFegin.addBalance(withdrawOrder.getAppcode(),
                withdrawOrder.getPaychannelid(),
                0-withdrawOrder.getAmount()+withdrawOrder.getCustomercommission(),
                2,
                withdrawOrder.getTradenum(),
                FlowTypeConstant.WITHDRAW,
                withdrawOrder.getAppcode(),
                "应用账户提现金额预占").getData();
        logger.debug("应用账户提现金额预占后:{}",accountChannelBalance);
        if (withdrawOrder.getCommission()>0) {
            accountChannelBalance = balanceFegin.addBalance(withdrawOrder.getAppcode(),
                    withdrawOrder.getPaychannelid(),
                    0 - withdrawOrder.getCommission(),
                    2,
                    withdrawOrder.getTradenum(),
                    FlowTypeConstant.WITHDRAW_COMMISSION,
                    withdrawOrder.getAppcode(),
                    "应用账户提现手续费预占").getData();
            logger.debug("应用账户提现手续费预占后:{}", accountChannelBalance);
        }
        return accountChannelBalance;
    }

    /**
     * 提现资金回滚
     * @param withdrawOrder
     * @return
     */
    public AccountChannelBalance withdrawRollback(WithdrawOrder withdrawOrder){
        AccountChannelBalance accountChannelBalance = balanceFegin.addBalance(withdrawOrder.getAccountid(),
                withdrawOrder.getPaychannelid(),
                withdrawOrder.getAmount()-withdrawOrder.getCustomercommission(),
                2,
                withdrawOrder.getTradenum(),
                FlowTypeConstant.WITHDRAW_ROLLBACK,
                withdrawOrder.getAppcode(),
                "账户提现金额回滚").getData();
        logger.debug("账户提现金额回滚后:{}",accountChannelBalance);
        if (withdrawOrder.getCustomercommission()>0) {
            accountChannelBalance = balanceFegin.addBalance(withdrawOrder.getAccountid(),
                    withdrawOrder.getPaychannelid(),
                    withdrawOrder.getCustomercommission(),
                    2,
                    withdrawOrder.getTradenum(),
                    FlowTypeConstant.WITHDRAW_COMMISSION_ROLLBACK,
                    withdrawOrder.getAppcode(),
                    "账户提现手续费回滚").getData();
            logger.debug("账户提现手续费回滚后:{}", accountChannelBalance);
        }
        return accountChannelBalance;
    }

    /**
     * 提现通道资金回滚
     * @param withdrawOrder
     * @return
     */
    public AccountChannelBalance withdrawChannelRollback(WithdrawOrder withdrawOrder){
        PayChannel payChannel = payChannelFegin.getPayChannel(withdrawOrder.getPaychannelid()).getData();
        AccountChannelBalance accountChannelBalance = balanceFegin.addBalance(payChannel.getAccountid().toString(),
                withdrawOrder.getPaychannelid(),
                withdrawOrder.getAmount()-withdrawOrder.getCustomercommission(),
                2,
                withdrawOrder.getTradenum(),
                FlowTypeConstant.WITHDRAW_ROLLBACK,
                withdrawOrder.getAppcode(),
                "通道账户提现金额回滚").getData();
        logger.debug("通道账户提现金额回滚后:{}",accountChannelBalance);
        if (withdrawOrder.getCommission()>0) {
            accountChannelBalance = balanceFegin.addBalance(payChannel.getAccountid().toString(),
                    withdrawOrder.getPaychannelid(),
                    withdrawOrder.getCommission(),
                    2,
                    withdrawOrder.getTradenum(),
                    FlowTypeConstant.WITHDRAW_COMMISSION_ROLLBACK,
                    withdrawOrder.getAppcode(),
                    "通道账户提现手续费回滚").getData();
            logger.debug("通道账户提现手续费回滚后:{}", accountChannelBalance);
        }
        return accountChannelBalance;
    }


    /**
     * 提现应用回滚
     * @param withdrawOrder
     * @return
     */
    public AccountChannelBalance withdrawAppRollback(WithdrawOrder withdrawOrder){
        AccountChannelBalance accountChannelBalance = balanceFegin.addBalance(withdrawOrder.getAppcode(),
                withdrawOrder.getPaychannelid(),
                withdrawOrder.getAmount()-withdrawOrder.getCustomercommission(),
                2,
                withdrawOrder.getTradenum(),
                FlowTypeConstant.WITHDRAW_ROLLBACK,
                withdrawOrder.getAppcode(),
                "应用账户提现金额回滚").getData();
        logger.debug("应用账户提现金额回滚后:{}",accountChannelBalance);
        if (withdrawOrder.getCommission()>0) {
            accountChannelBalance = balanceFegin.addBalance(withdrawOrder.getAppcode(),
                    withdrawOrder.getPaychannelid(),
                    withdrawOrder.getCommission(),
                    2,
                    withdrawOrder.getTradenum(),
                    FlowTypeConstant.WITHDRAW_COMMISSION_ROLLBACK,
                    withdrawOrder.getAppcode(),
                    "应用账户提现手续费回滚").getData();
            logger.debug("应用账户提现手续费回滚后:{}", accountChannelBalance);
        }
        return accountChannelBalance;
    }



    /**
     * 提现通道执行操作
     */
    public WithdrawOrder withdrawProcessing(WithdrawOrder withdrawOrder){
        //TODO
        return withdrawOrder;
    }


    /**
     * 提现回调处理
     */
    public void withdrawCallback(String tradenum,int status,String failreason){
        WithdrawOrder withdrawOrder = withdrawOrderFegin.queryWithdrawOrder(tradenum).getData();
        if (withdrawOrder == null) {
            logger.debug("{}提现订单不存在，无法进行回调处理");
            return;
        }
        if (status == 1)
            withdrawSuccess(withdrawOrder);
        if (status == 0)
            withdrawFail(withdrawOrder,failreason);
    }


    /**
     * 提现成功操作
     */
    public void withdrawSuccess(WithdrawOrder withdrawOrder){
        switch (withdrawOrder.getStatus()) {
            case WithdrawStatusConstant.SUCCESS:
                logger.debug("{}提现订单已经成功，不可重复处理");
                break;
            case WithdrawStatusConstant.ACCEPTING:
                withdrawOrder.setStatus(WithdrawStatusConstant.SUCCESS);
                withdrawOrder.setTransferredtime(new Date());
                withdrawOrder.setFailreason("交易成功");
                withdrawOrderFegin.updateWithdrawOrder(withdrawOrder);
                rabbitMQSender.send(RabbitMqQueueNameConstant.NOTIFY_WITHDRAWAL, withdrawOrder.getTradenum());
                break;
            case WithdrawStatusConstant.FAIL:
                //删除已回滚记录
                flowFegin.deleteAccountBalanceFlow(withdrawOrder.getTradenum());
                //重新扣除账户资金
                withdrawDeduct(withdrawOrder);
                //重新扣除通道账户资金
                withdrawChannelDeduct(withdrawOrder);
                //重新扣除应用账户资金
                withdrawAppDeduct(withdrawOrder);
                //修改订单状态
                withdrawOrder.setStatus(WithdrawStatusConstant.SUCCESS);
                withdrawOrder.setTransferredtime(new Date());
                withdrawOrder.setFailreason("交易成功");
                withdrawOrderFegin.updateWithdrawOrder(withdrawOrder);
                rabbitMQSender.send(RabbitMqQueueNameConstant.NOTIFY_WITHDRAWAL, withdrawOrder.getTradenum());
                break;
        }
    }

    /**
     * 提现失败操作
     */
    public void withdrawFail(WithdrawOrder withdrawOrder,String failreason){
        if (withdrawOrder.getStatus() != WithdrawStatusConstant.FAIL) {
            withdrawOrder.setTransferredtime(new Date());
            withdrawOrder.setStatus(WithdrawStatusConstant.FAIL);
            withdrawOrder.setFailreason(failreason);
            withdrawOrderFegin.updateWithdrawOrder(withdrawOrder);
            //账户资金回滚
            withdrawRollback(withdrawOrder);
            //通道账户资金回滚
            withdrawChannelRollback(withdrawOrder);
            //应用账户资金回滚
            withdrawAppRollback(withdrawOrder);
            //通知应用
            rabbitMQSender.send(RabbitMqQueueNameConstant.NOTIFY_WITHDRAWAL, withdrawOrder.getTradenum());
        }else
            logger.debug("{}提现订单已经失败，不可重复失败处理",withdrawOrder.getTradenum());
    }

    /**
     * 提现查单处理
     */



}
